#include "Storage/ConnectionConfigCollection.hpp"
#include "Storage/ConnectionConfig.hpp"
#include "Storage/ConnectionConfigFactory.hpp"
#include <boost/iterator/indirect_iterator.hpp>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cassert>

namespace Storage
{

ConnectionConfigCollection::ConnectionConfigCollection( ConnectionConfigFactory& factory )
	: rConnCfgFactory_( factory)
{
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::addConnectionConfig( ConnectionConfig* pNewConnConfig)
{
	assert( connConfigs_.end() == std::find( connConfigs_.begin(), connConfigs_.end(), pNewConnConfig));
	connConfigs_.push_back( pNewConnConfig);
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::removeConnectionConfig( ConnectionConfig* pExstingConnConfig)
{
	std::remove( connConfigs_.begin(), connConfigs_.end(), pExstingConnConfig);
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::store( std::ostream& os)
{
	using namespace boost;

	indirect_iterator< Iterator, ConnectionConfig> curI = connConfigs_.begin(),
			endI = connConfigs_.end();
	while( curI != endI)
	{
		curI->store( os);
		++curI;
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::store( const std::string& fileName )
{
	try
	{
		std::ofstream of( fileName.c_str(), std::ios::trunc | std::ios::out);
		if( !of.fail())
		{
			this->store( of);
		}
	}
	catch( ...)
	{
		// TODO: Exception handling
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::load( std::istream& is)
{
	while( !is.eof())
	{
		std::string connHeader;
		std::getline( is, connHeader);
		std::string connType, connName;
		// TODO: Improve reliability
		assert( '[' == connHeader[0]);
		std::string::size_type pos = connHeader.find( ']', 1);
		connType = connHeader.substr( 1, pos - 1);
		++pos;++pos;
		connName = connHeader.substr( pos);
		std::auto_ptr< ConnectionConfig> pCfg( rConnCfgFactory_.createConfig( connType, connName));
		pCfg->load( is);
		connConfigs_.push_back( pCfg.release());
	}
}

// ---------------------------------------------------------------------------------------------------------------------

void ConnectionConfigCollection::load( const std::string& fileName )
{
	try
	{
		std::ifstream fstrm( fileName.c_str());
		if( !fstrm.fail())
		{
			this->load( fstrm);
		}
	}
	catch( ...)
	{
		// TODO: Exception handling when loading the connection configurations.
	}
}

// ---------------------------------------------------------------------------------------------------------------------


} // namespace Storage
